#!/bin/bash

# #!/bin/sh

# ## 使用方法：
#  /path/quick_vim/astyle.sh          格式化当前文件夹下代码
#  /path/quick_vim/astyle.sh -r       递归查找子文件夹
#  /path/quick_vim/astyle.sh -f xxx.c 格式化指定文件代码
#  /path/quick_vim/astyle.sh -f *.c   格式化指定文件代码


# --style=kr： K&R 风格由 Brian Kernighan 和 Dennis Ritchie 共同开发，是最早的一种代码风格之一，主要用于 C 语言程序中。
#              它的特点是函数或控制结构的左括号 { 紧接在语句的末尾，而不是在下一行;
# --style=linux： Linux Kernel 风格是 Linux 内核开发所使用的代码风格，它与 K&R 风格非常相似，但有一些细微的差别，特别是在缩进方面。
# --style=bsd:  Allman 风格（也称为 BSD 风格）是由 Eric Allman 开发的。它与 K&R 风格最大的区别在于左括号 { 是放在新的一行，而不是放在语句的末尾。

# style_opt="--style=linux --delete-empty-lines --break-blocks=all"
style_opt="--style=bsd --indent-switches"

# 运行 astyle 的命令及其选项
astyle_command="astyle $style_opt --lineend=linux --pad-oper --unpad-paren --pad-header
--convert-tabs --indent=spaces=4 --indent-labels --indent-preprocessor --preserve-date
--align-pointer=name --align-reference=name --keep-one-line-statements --attach-namespaces
--max-instatement-indent=120 --suffix=none --add-brackets --pad-comma --break-after-logical"

# astyle_command="astyle --style=linux --lineend=linux --pad-oper --unpad-paren --pad-header
# --convert-tabs --indent=spaces=4 --indent-labels --indent-preprocessor --preserve-date
# --align-pointer=name --align-reference=name --keep-one-line-statements --attach-namespaces
# --max-instatement-indent=120 --suffix=none --add-brackets --pad-comma --break-after-logical
# --delete-empty-lines --break-blocks=all"


# --indent=spaces=4：指定代码缩进为 4个空格。这定义了代码的缩进样式，将代码块的内容缩进 4 个空格。
# --indent-labels：缩进标签（通常是 `goto` 语句的标签）。这选项将标签与代码块的缩进一致。
# --pad-oper：在操作符周围添加空格。这可以增加代码的可读性，使操作符与操作数之间有一些空间。
# --unpad-paren：去除括号周围的空格。这将去除括号周围的空格，以提高代码的一致性。
# --pad-header：在函数声明和定义的括号周围添加空格。这用于增加代码的可读性和一致性。
# --keep-one-line-statements：保持单行语句不换行。这将确保单行语句不会被换行成多行，使代码更紧凑。
# --keep-one-line-blocks: 保持单行代码块不换行。这确保了单行代码块不会被换行，使代码更紧凑。
# --break-blocks=all：将大括号放在新的一行。这选项将确保大括号独占一行。
# --convert-tabs：将制表符转换为空格。这会将制表符替换为指定数量的空格，以确保代码中的缩进一致。
# --indent-preprocessor：缩进预处理器指令（如 `#define`、`#ifdef` 等）。这确保了预处理器指令与代码块的缩进一致。
# --indent-switches：缩进switch块
# --indent-cases：缩进case
# --align-pointer=name：对齐指针变量名。这将使指针变量名的对齐方式更加一致，使代码更容易阅读。
# --align-reference=name：对齐引用变量名。这将对齐引用变量名的方式更一致，增加了代码的可读性。
# --attach-namespaces：将命名空间的大括号附加到名称之后。这改变了命名空间的大括号位置，将其附加到命名空间名称之后。
# --preserve-date: 不修改时间
# --max-instatement-indent=120：设置内部代码块的最大缩进为 120 个字符。这可以限制代码块的缩进深度，以防止过于深的嵌套。
# --align-switch-colon：对齐 `switch` 语句中的 `case` 标签冒号。
# --align-reference=type：对齐引用变量的类型。这选项将引用变量名对齐到其类型的最后一个字符，以提高代码的可读性。
# --add-brackets：为单行的控制结构（如 `if`、`for`、`while` 等）添加大括号。
# --break-return-type：将函数声明的返回类型和函数名分开放置。这将返回类型与函数名分开，以提高代码的可读性。
# --delete-empty-lines: 删除所有空行
# --break-after-logical: 在逻辑运算符后分行
# --pad-comma: 在逗号后添加空格

# 定义变量来控制递归和指定文件
recursive=0
file=0
SRC_PATH=`pwd`

echo $SHELL

# set source path
case $1 in
    -r)
        echo " recursive path: ${SRC_PATH}"
        ;;
    -f)
        echo " astyle file: ${SRC_PATH}/$2"
        ;;
esac

cd ${SRC_PATH}

echo "# switch to $SRC_PATH"
echo "---------"

orig_optind=$OPTIND

# 解析脚本参数
while getopts "rf:" opt; #选项后面的冒号表示该选项需要参数:
do
    case $opt in
        r)
            recursive=1
            ;;
        f)
            # echo "f's arg:$OPTARG" #参数存在$OPTARG中
            file=1
            ;;
        ?)
            echo "unkonw argument"
            exit 1
            ;;
    esac
done


# 定义要格式化的文件类型（例如，C 源文件和头文件）
file_extensions=("c" "h" "cpp")

# 恢复 OPTIND 的值
OPTIND=$orig_optind

# 检查脚本参数来确定要执行的操作
if [ $recursive -eq 1 ]; then
    # 递归格式化当前文件夹及其子文件夹下的文件
    for ext in "${file_extensions[@]}"
    do
        find . -type f -name "*.$ext" -exec $astyle_command {} \;
    done

elif [ $file -eq 1 ]; then
    # 格式化特定的文件
    shift $((OPTIND))
    for file in "$@"
    do
        if [ -f "$file" ]; then
            $astyle_command "$file"
        else
            echo "File not found: $file"
        fi
    done

else
    # 格式化当前文件夹下的文件，不进行递归
    for ext in "${file_extensions[@]}"
    do
        find . -maxdepth 1 -type f -name "*.$ext" -exec $astyle_command {} \;
    done
fi

echo "---------"
echo "# astyle done!"
echo "---> HAPPY HACKING! <---"

